package tree;

import java.util.LinkedList;
import java.util.Stack;

/**
 * @author zhaoziqiang
 * @Description: 二分搜索树
 * @date 2020/9/2 17:18
 */
public class BStree<E extends Comparable<E>> {

    private class Node {
        public E e;
        public Node left, right;

        public Node(E e) {
            this.e = e;
            this.left = null;
            this.right = null;
        }
    }

    private Node root;
    private int size;

    public BStree() {
        this.root = null;
        this.size = 0;
    }

    private int getSize() {
        return size;
    }

    private boolean isEmpty() {
        return size == 0;
    }

    public void add(E e) {
        root = addNode(root, e);
    }

    //    //向以node为根节点二分搜索树中插入元素e，递归算法
    //    private void addNode(Node node, E e) {
    //        if(node.e==e)
    //            return;
    //        else if(e.compareTo(node.e)<0 && node.left==null)
    //            node.left=new Node(e);
    //        else if(e.compareTo(node.e)>0 && node.right==null)
    //            node.right=new Node(e);
    //        else if(e.compareTo(node.e)<0)
    //            addNode(node.left,e);
    //        else
    //            addNode(node.right,e);
    //    }
    //返回新插入节点后二分搜索树的跟
    private Node addNode(Node node, E e) {
        if (node == null) {
            size++;
            return new Node(e);
        } else if (e.compareTo(node.e) < 0)
            node.left = addNode(node.left, e);
        else
            node.right = addNode(node.right, e);
        return node;
    }

    //是否包含某元素
    public boolean contains(E e) {
        return contains(root, e);
    }

    //查询以node为根的二分搜索树是否包含元素e,递归算法
    private boolean contains(Node node, E e) {
        if (node == null) {
            return false;
        } else if (e.compareTo(node.e) == 0) {
            return true;
        } else if (e.compareTo(node.e) < 0) {
            return contains(node.left, e);
        } else {
            return contains(node.right, e);
        }
    }

    //前序遍历以node为跟的二分搜索树
    public void preOrder() {
        preOrder(root);
    }

    private void preOrder(Node node) {
        if (node == null)
            return;
        System.out.println(node.e);
        preOrder(node.left);
        preOrder(node.right);
    }

    //前序遍历以node为跟的二分搜索树（非递归）
    public void preOrderNR() {
        Stack<Node> stack = new Stack<>();
        stack.push(root);
        while (!stack.isEmpty()) {
            Node cur = stack.pop();
            System.out.println(cur.e);
            if (cur.right != null)
                stack.push(cur.right);
            if (cur.left != null)
                stack.push(cur.left);
        }
    }

    //层序遍历
    public void levelTraversal() {
        java.util.Queue<Node> linkedList = new LinkedList<>();
        linkedList.add(root);
        while (!linkedList.isEmpty()) {
            Node cur = linkedList.remove();
            System.out.println(cur.e);
            if (cur.left != null)
                linkedList.add(cur.left);
            if (cur.right != null) {
                linkedList.add(cur.right);
            }
        }
    }

    //中序遍历以node为根的二分搜索树 （应用：由小到大,顺序输出）
    public void inOrder() {
        inOrder(root);
    }

    private void inOrder(Node node) {
        if (node == null)
            return;
        inOrder(node.left);
        System.out.println(node.e);
        inOrder(node.right);
    }

    //后序遍历以node为根的二分搜索树
    public void postOrder() {
        postOrder(root);
    }

    private void postOrder(Node node) {
        if (node == null)
            return;
        postOrder(node.left);
        postOrder(node.right);
        System.out.println(node.e);
    }

    //返回以node为跟的最小节点
    public E miniNode() {
        if (size == 0)
            throw new IllegalArgumentException("BStree is Empty!");
        return miniNode(root).e;
    }

    private Node miniNode(Node node) {
        if (node.left == null)
            return node;
        return miniNode(node.left);
    }

    //返回以node为跟的最大节点
    public E maxNode() {
        if (size == 0)
            throw new IllegalArgumentException("BStree is Empty!");
        return maxNode(root).e;
    }

    private Node maxNode(Node node) {
        if (node.right == null)
            return node;
        return maxNode(node.right);
    }

    //删除最小值所在节点并返回最小值
    public E removeMini() {
        E e = miniNode();
        removeMini(root);
        return e;

    }

    //删除以node为跟的二分搜索树最小节点
    //返回删除节点后新的二分搜索树的跟
    private Node removeMini(Node node) {
        if (node.left == null) {
            Node right = node.right;
            node.right = null;
            size--;
            return right;
        }
        node.left = removeMini(node.left);
        return node;
    }
    //删除最小值所在节点并返回最小值
    public E removeMax() {
        E e = maxNode();
        removeMax(root);
        return e;

    }

    //删除以node为跟的二分搜索树最大节点
    //返回删除节点后新的二分搜索树的跟
    private Node removeMax(Node node) {
        if (node.right == null) {
            Node left = node.left;
            node.left = null;
            size--;
            return left;
        }
        node.right = removeMax(node.right);
        return node;
    }
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        generateStr(root, 0, sb);
        return sb.toString();
    }

    private void generateStr(Node root, int depth, StringBuilder sb) {
        if (root == null) {
            sb.append(generateStrDepth(depth) + "null\n");
            return;
        }
        sb.append(generateStrDepth(depth) + root.e + "\n");
        generateStr(root.left, depth + 1, sb);
        generateStr(root.right, depth + 1, sb);
    }

    private String generateStrDepth(int depth) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < depth; i++) {
            sb.append("--");
        }
        return sb.toString();
    }

}

